package com.wthink.hzgj.util

import android.util.Log
import com.wthink.hzgj.Constants.ROOT
import java.io.File
import java.io.FileOutputStream
import java.io.OutputStream
import java.io.PrintStream
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.ArrayBlockingQueue

object Log {

    val TAG = "BUS"

    private val queue = ArrayBlockingQueue<Any>(128)
    private val mMaxSize = 1024 * 1024
    private val dir = "${ROOT}/log"
    private val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    private val lineSeparator = "\r\n".toByteArray()
    private fun moment(): String = sdf.format(Date())

    @JvmField
    val trace: Boolean

    init {
        startLog()
//        trace = runBlocking(Dispatchers.IO) {
//            "trace".equals(SettingWithCacheRepository.findSetting(SettingKey.LOG))
//        }
        trace = true
    }


    @JvmStatic
    fun debug(msg: String) {
        if (trace) {
            log("${Thread.currentThread().name}$ ${msg}")
        } else {
            Log.d(TAG, msg)
        }
    }

    fun debug(msg: String, err: Throwable? = null) {
        if (trace) {
            log(msg, err)
        } else {
            Log.d(TAG, msg, err)
        }
    }

    fun error(msg: String, err: Throwable? = null) {
        Log.e(TAG, msg, err)
        log(msg, err)
    }

    private fun log(msg: String, err: Throwable? = null) {
        queue.put(msg)
        if (err != null) {
            queue.put(err)
        }
    }

    private fun getWriter(file: String = "debug.log"): OutputStream {
        val logFile = File("$dir/${file}")
        if (!logFile.exists()) {
            val dirFile = File(dir)
            if (!dirFile.exists()) {
                dirFile.mkdirs()
            }
            logFile.createNewFile()
        }

        if (logFile.length() > mMaxSize) {
            logFile.renameTo(File("$dir/$file.bak"))
            logFile.createNewFile()
        }

        return FileOutputStream(logFile, true)
    }

    private fun startLog() {
        Thread {
            var getWriterAt = 0L
            val timeout = 1000 * 60
            var writer: OutputStream? = null

            while (true) {
                try {
                    val msg = queue.take()
                    val now = System.currentTimeMillis()
                    if (writer == null) {
                        writer = getWriter()
                        getWriterAt = now
                    } else if (now - getWriterAt > timeout) {
                        try {
                            writer.flush()
                            writer.close()
                        } catch (err: Throwable) {
                        }
                        writer = getWriter()
                        getWriterAt = now
                    }

                    writer.write(lineSeparator)
                    when (msg) {
                        is String -> {
                            writer.write("${moment()}:${msg}".toByteArray())
                        }
                        is Throwable -> {
                            msg.printStackTrace(PrintStream(writer))
                        }
                    }
                } catch (err: Throwable) {
                    writer = null
                    Log.e(TAG, "记录日志失败", err)
                }
            }
        }.start()
    }
}